Introducción a R

Crear código en R, uso colaborativo y reproducible

Bienvenidxs!!

¿Quiénes somos?

Organización del curso

Por día

Lunes = introducción a R, crear código, buenas prácticas
Martes = manejo y visualizacion de datos
Miércoles = modelos lineales y factoriales
Jueves = modelos generalizados y multivariantes
Viernes = uso colaborativo, dudas, ejemplos

Por hora

  • 9 a 10 teoría
  • 10 a 10:45 ejercicios
  • 10:45 a 11 break
  • 11 a 12 teoría
  • 12 a 13 ejercicios y dudas

Hoy

  • Introducción, código básico
  • Ejercicios I
  • Funciones, bucles, dataframes
  • Ejercicios II y III

Lo que vas a aprender:

  • Mejorar la comprensión y la práctica estadística.

  • Desarrollar habilidades en programación en R.

  • Aprender flujos de trabajo eficientes, limpios y reproducibles.

  • Saber buscar información

  • No enredarse en errores

Lo que no vas a aprender

  • A programar en plan pro sin mirar internet o chatgpt

  • A hacer páginas web

  • A dejar de pelearte con la estadística

Objetivos de la clase

WordCloud

Introducción

R es un lenguaje y entorno de programación especializado en:

Análisis estadístico, visualización de datos y ciencia de datos.

Utilizado por investigadores, analistas y científicos para explorar, modelar y comunicar información basada en datos de forma eficiente y reproducible.

Muy utilizado en biología

Biólogxs en general

R y Rtudio

R → Es el lenguaje de programación y el motor que realiza los cálculos estadísticos y el análisis de datos.

RStudio → Es un entorno de desarrollo integrado (un programa) que facilita el uso de R con una interfaz amigable, paneles, autocompletado y herramientas visuales.

Ejemplo mesa de trabajo

¿Qué puede hacer R?

  • Calcular y analizar (operaciones matemáticas, modelos, simulaciones, tests…)
  • Trabajar con datos (leer y escribir tablas, limpiar datos, transformar datos)
  • Visualizar (graficos estadísticos, interactivos, mapas, animaciones, etc)
  • Automatizar y extender (crear funciones propias, desarrollar paquetes, reproducir analisis facilmente)
  • Comunicar (crear informes Quarto o RMarkdown, crear webs o apps Shiny) Ejemplo quarto ## Workflow: lo básico básico

Es una calculadora: se pueden hacer operaciones básicas multiplicar, dividir, sumar, restar…

2 + 3     
[1] 5
10 - 4    
[1] 6
3 * 5     
[1] 15
20 / 4    
[1] 5

Operaciones básicas de lógica

Las operaciones lógicas comparan valores y devuelven un resultado lógico.

TRUE se comporta como 1 y FALSE como 0. Se pueden sumar o usar en cálculos.

20 / 4 >= 10    # ¿5 es mayor o igual que 10? → FALSE
[1] FALSE
20 / 4 == 10    # ¿5 es igual a 10? → FALSE
[1] FALSE
20 / 4 < 10     # ¿5 es menor que 10? → TRUE
[1] TRUE
valores <- c(TRUE, FALSE, TRUE, TRUE)
sum(valores)       # cuenta cuántos TRUE hay
[1] 3
mean(valores)      # proporción de TRUE
[1] 0.75

Cuidado que en R “=” y “<-” son sinónimos!

Acumular información

La magia de los objetos

x <- 10    
y <- 5
suma <- x + y
suma
[1] 15
suma + 7
[1] 22

Espera, pero ¿qué son los objetos?

Los objetos empiezan por una letra

Son sensibles a mayusculas

Tienen que llevar nombres coherentes y un orden

yo_uso_la_serpiente <- 10
OtraGenteUsaElCamello <- 9
otra.gente.usa.los.puntos <- 9
Hayque_evitar.esto10 <- 2

Tipos de objetos

Hay muuchos tipos de objetos

  • numéricos, caracteres, matrices, tablas, listas
  • modelos, polígonos, funciones
numero <- 1:10
numero
 [1]  1  2  3  4  5  6  7  8  9 10
caracter <- "del uno al diez"
caracter
[1] "del uno al diez"
una_lista <- list(1:10, 11:20, 21:30)
una_lista
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
 [1] 11 12 13 14 15 16 17 18 19 20

[[3]]
 [1] 21 22 23 24 25 26 27 28 29 30

Podemos transformar objetos de un tipo en otro con as.xxxx()

numeros_como_caracteres <- as.character(numero)
numeros_como_caracteres
 [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10"
numeros <- as.numeric(numeros_como_caracteres)
numeros
 [1]  1  2  3  4  5  6  7  8  9 10

Vectores y operaciones con vectores

Creamos vectores, que son elementos del mismo tipo juntos (numérico, carácter). Es un poco como una fila de una tabla… se pueden crear con 1:10 (numeros del 1 al 10)

Consecutivos del 1:10

Combinando c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Generador de secuencias: del 0 al 100 cada 10 seq(0, 100, 10)

numeros <- c(1, 2, 3, 4, 5) 
numeros
[1] 1 2 3 4 5
otros_numeros <- 1:40
otros_numeros
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
[26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
otros_numeros + 10
 [1] 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
[26] 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
promedio <- mean(numeros)
promedio
[1] 3
promedio * numeros
[1]  3  6  9 12 15
numeros / otros_numeros
 [1] 1.00000000 1.00000000 1.00000000 1.00000000 1.00000000 0.16666667
 [7] 0.28571429 0.37500000 0.44444444 0.50000000 0.09090909 0.16666667
[13] 0.23076923 0.28571429 0.33333333 0.06250000 0.11764706 0.16666667
[19] 0.21052632 0.25000000 0.04761905 0.09090909 0.13043478 0.16666667
[25] 0.20000000 0.03846154 0.07407407 0.10714286 0.13793103 0.16666667
[31] 0.03225806 0.06250000 0.09090909 0.11764706 0.14285714 0.02777778
[37] 0.05405405 0.07894737 0.10256410 0.12500000
# [ ] para seleccionar partes de un vector o una tabla
(numeros / otros_numeros)[8]
[1] 0.375

Generadores de distribuciones

R es muy potente generando distribuciones.
Una distribución describe cómo se reparten los valores de una variable.

Números al azar → todos con la misma probabilidad UNIFORME ### Ejemplo Distribución uniforme

# Un vector de 5 números aleatorios con distribución uniforme
runif(5)
[1] 0.30386252 0.05295652 0.59232550 0.82649434 0.46938448
# Ahora que 3 números vayan del 0 al 100
runif(3, min=0, max=100)
[1] 92.80687 74.29579 90.39731
# Cómo se ve
x <- runif(1000, min = 0, max = 100)
hist(x, col = "orange", main = "Distribución uniforme", xlab = "Número de eventos", ylab = "Frecuencia")

Distribución normal

Alturas de personas → muchas alrededor del promedio (forma de campana) NORMAL

# 4 números con una distribución normal
rnorm(4)
[1]  1.1308427 -0.2555750 -0.4187162  0.0651027
# Especificando la media y la desviación
x <- rnorm(1000, mean = 50, sd = 10)
hist(x, col = "skyblue", main = "Distribución normal", xlab = "Número de eventos", ylab = "Frecuencia")

Distribución poisson

Conteo POISSON

# Generar 1000 observaciones con media (λ) = 3
x <- rpois(1000, lambda = 3)

# Ver las primeras observaciones
head(x)
[1] 4 4 4 0 1 2
# Histograma
hist(x, col = "lightgreen", main = "Distribución de Poisson (λ = 3)", xlab = "Número de eventos", ylab = "Frecuencia")

Distribución binomial negativa

Resultados de “éxito o fracaso” (como lanzar una moneda) BINOMIAL

# Binomial
# 20 experimentos, en cada uno lanzamos una monedas, con una probabilidad de que salga cara del 50%
caras <- rbinom(200, size = 1, prob = 0.5)
table(caras)
caras
  0   1 
105  95 
barplot(table(caras), col = "steelblue")

Funciones básicas y útiles

Las funciones son aplicaciones que nos permiten realizar operaciones muy diversas.

  • Funciones que vienen con la distribución base de R o en los paquetesya creados por los usuarios
# c () concatenar
x <- c(4, 6, 8, 3, 9, 12, 12)

# Estadísticos básicos
mean(x)       # media
[1] 7.714286
median(x)     # mediana
[1] 8
sd(x)         # desviación estándar
[1] 3.59232
min(x)        # valor mínimo
[1] 3
max(x)        # valor máximo
[1] 12
range(x)      # rango (min, max)
[1]  3 12
summary(x)    # resumen general
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  3.000   5.000   8.000   7.714  10.500  12.000 

Ayuda

Ayuda para funciones en R (o también vale buscar en google “function mean in R”)

# Ayudas
?mean           # abre la ayuda de una función
help(mean)      # lo mismo que '?mean'
??"normal"      # búsqueda más amplia en toda la documentación
example(mean)   # muestra ejemplos prácticos

mean> x <- c(0:10, 50)

mean> xm <- mean(x)

mean> c(xm, mean(x, trim = 0.10))
[1] 8.75 5.50

Mas funciones básicas y útiles

Aleatoriedad

x <- rpois(8, 8)
x
[1]  3  7 11  5  6  5  9  8
sample(x, 3)          # elegir 3 elementos al azar
[1] 9 6 5
rev(x)                # invertir el orden
[1]  8  9  5  6  5 11  7  3
sort(x)               # ordenar valores
[1]  3  5  5  6  7  8  9 11

Conteos y valores únicos

length(x)             # longitud del vector
[1] 8
table(x)              # tabla de frecuencias
x
 3  5  6  7  8  9 11 
 1  2  1  1  1  1  1 
unique(x)             # valores únicos
[1]  3  7 11  5  6  9  8
length(unique(x))     # cuántos valores distintos
[1] 7
sample(x, 3, replace=TRUE) 
[1] 5 9 5
round(mean(x), 2)     # redondear a 2 decimales
[1] 6.75

Nombres y texto

nombres <- c("Laura", "Rocio", "Violeta", "Rocio", "Rocio")
unique (nombres)
[1] "Laura"   "Rocio"   "Violeta"
table (nombres)
nombres
  Laura   Rocio Violeta 
      1       3       1 
rep (nombres, 5)    # repetir algo varias veces
 [1] "Laura"   "Rocio"   "Violeta" "Rocio"   "Rocio"   "Laura"   "Rocio"  
 [8] "Violeta" "Rocio"   "Rocio"   "Laura"   "Rocio"   "Violeta" "Rocio"  
[15] "Rocio"   "Laura"   "Rocio"   "Violeta" "Rocio"   "Rocio"   "Laura"  
[22] "Rocio"   "Violeta" "Rocio"   "Rocio"  
sample(nombres, 3, replace=TRUE) 
[1] "Rocio"   "Rocio"   "Violeta"

Ejercicios I

# 1. Calcula el minimo valor de 100 valores aleatorios según una distribución normal
min (rnorm (100))
[1] -2.846955
# 2. Dada una secuencia de 20 números seguidos (del 0 al 20), genera los pares y guárdalo en un objeto.
pares <- seq (0, 20, 2)

# 3. Ejercicio:

  # Crea un vector con 20 números aleatorios entre 0 y 50.
  # Calcula el promedio y la desviación estándar.
  # Multiplica todos los valores por 2.
  # Dibuja un histograma.
  #¿Cómo cambia el promedio después de multiplicar por 2?

mi_vector <- runif(20,0,50)
mean (mi_vector)
[1] 30.40114
sd (mi_vector)
[1] 14.64594
mi_vector_2 <- mi_vector*2
hist(mi_vector_2)
# Crea un vector con edades y usa una comparación para saber cuáles son mayores de edad y cualcula cuantos no lo son
edades <- c(12, 18, 3, 44, 25, 15, 30)
sum (edades > 18)
[1] 3

Crear funciones

  • Crear nuestras propias funciones con function().
  • Asignarle un nombre
  • Indicar argumentos
  • Escribir entre llaves el código

Ejemplo de funciones

# Queremos la media de nuestros números transformados a logaritmo

vector <- seq(1, 100, 10)
mean (log (vector))
[1] 3.380067
sd (log (vector))
[1] 1.355705
# Queremos hacerlo otra vez con otros valores

vector2 <- seq(1, 300, 50)
mean (log (vector2))
[1] 4.065497
sd (log (vector2))
[1] 2.069674
log_vect <- function (y) {
  mean_y <- mean (log (y+1))
  sd_y <- sd (log (y+1))
  print(paste("La media es", mean_y, ", la desviación estándar es:", round(sd_y,2)))
  return(log(y))
}

vector3 <- seq(1, 300, 4)
distribution = log_vect (vector3)
[1] "La media es 4.70839604852934 , la desviación estándar es: 0.98"
hist(distribution)

Bucles - for ()

R repite algo automáticamente sin que lo escribas varias veces.

[paste(“Aquí está el número”, 1)
paste(“Aquí está el número”, 2)
paste(“Aquí está el número”, 3)
paste(“Aquí está el número”, 4)
paste(“Aquí está el número”, 5)] {style=“font-size: 0.2em !important;”}

# i puede ser un número
length(1:5) # número de iteraciones 
[1] 5
for (i in 1:5) {
  print(paste("Aquí está el número", i))
}
[1] "Aquí está el número 1"
[1] "Aquí está el número 2"
[1] "Aquí está el número 3"
[1] "Aquí está el número 4"
[1] "Aquí está el número 5"
# i puede ser un caracter 
nombres <- c ("Laura", "Rocio", "Violeta")
length(nombres) #número de iteraciones 
[1] 3
for (i in nombres) {
  print(paste("Aquí está la alumna", i))
}
[1] "Aquí está la alumna Laura"
[1] "Aquí está la alumna Rocio"
[1] "Aquí está la alumna Violeta"

Bucles II

Con un dado ahora

# un dado
sample(1:6, 1)
[1] 5
# i puede ser solo el numero de veces que repetimos algo
resultados <- c()
for (i in 1:100) {
  tiro <- sample(1:6, 1)
  resultados <- c(resultados, tiro)
}

resultados
  [1] 5 2 3 2 4 1 1 4 5 1 2 2 4 5 3 4 5 6 3 1 5 5 1 3 6 3 1 4 1 1 6 4 4 2 1 1 4
 [38] 6 6 6 6 1 2 4 4 1 1 4 1 5 3 3 4 5 2 3 4 3 3 5 6 5 1 6 5 6 2 4 6 2 6 5 6 1
 [75] 3 6 6 2 6 4 4 5 3 6 1 5 6 4 5 6 1 6 2 6 5 6 2 2 2 5
mean(resultados)
[1] 3.67
# 1. Ejercicio: como podemos saber cuantas veces ha salido el numero 2?
sum(resultados==2)
[1] 14

Volvemos a nuestro ejemplo

# Queremos repetir el cálculo de media y desviación logarítmica

# para varios vectores distintos

vectores <- list(
seq(1, 100, 10),
seq(1, 300, 50),
seq(1, 500, 100)
)

# Creamos un bucle FOR

for (i in vectores) {
media <- mean(log(i + 1))
desv  <- sd(log(i + 1))
print(paste("Media:", round(media, 2), " | Desviación:", round(desv, 2)))
}
[1] "Media: 3.48  | Desviación: 1.16"
[1] "Media: 4.19  | Desviación: 1.8"
[1] "Media: 4.47  | Desviación: 2.17"
# Ahora queremos guardar los resultados

# Crear un vector vacío

resultados <- c()

for (i in vectores) {
media <- mean(log(i + 1))
desv  <- sd(log(i + 1))
filas <- data.frame(media=media, desv=desv)
resultados <- rbind(resultados, filas)
}

resultados
     media     desv
1 3.475605 1.164002
2 4.188490 1.800784
3 4.466653 2.171404

Apply, sapply, lapply

Otra forma de hacer bucles, pero en la misma linea

sapply(vectores, function(i) mean(log(i + 1)))
[1] 3.475605 4.188490 4.466653

ifelse

Condicionantes

if: R ejecuta el código dentro del bloque {} solo si la condición es verdadera.
if // else: si no se cumple la condición, haz esto otro
ifelse: lo mismo pero en una sola linea

x <- 10

if (x > 5) {
  print("El número es mayor que 5")
}
[1] "El número es mayor que 5"
x <- 3

if (x > 5) {
  print("El número es mayor que 5")
} else {
  print("El número es menor o igual que 5")
}
[1] "El número es menor o igual que 5"
edades <- c(15, 22, 35, 12)

ifelse(edades >= 18, "Adulto", "Menor")
[1] "Menor"  "Adulto" "Adulto" "Menor" 

Ejercicios 2

  1. Haz una función que me diga si un número cualquiera es par o no

  2. Crea un vector con 10 temperaturas y usa ifelse() para clasificar cada valor como “Frío” o “Caluroso”

que_tipo_de_numero_soy <- function (x) {
ifelse(x %% 2 == 0, "par", "impar")
}

temperaturas <- rpois (10, 15)
clasificacion <- ifelse(temperaturas < 15, "frio", "caliente")
# Añade a una tabla esta clasificación
data.frame (temperaturas, clasificacion)
   temperaturas clasificacion
1             7          frio
2            18      caliente
3            15      caliente
4            15      caliente
5            14          frio
6            12          frio
7            12          frio
8            10          frio
9            14          frio
10           20      caliente

Bases de datos

Una base de datos (data frame) es una tabla de datos, como una hoja de cálculo en excel, tiene filas (observaciones) y columnas (variables).

# Creamos vectores con información
nombres <-  c ("Laura", "Rocio", "Violeta")
edad <- c(23, 35, 29)
altura <- c(1.65, 1.80, 1.70)
profesion <- c("Bióloga", "Profesora", "Médica")

# Combinamos todo en un data frame
personas <- data.frame(
  NAME = nombres,
  AGE = edad,
  HEIGHT = altura,
  JOB = profesion)

personas[1,]
   NAME AGE HEIGHT     JOB
1 Laura  23   1.65 Bióloga
personas[,1]
[1] "Laura"   "Rocio"   "Violeta"
personas$NAME # Seleccionar columnas con $
[1] "Laura"   "Rocio"   "Violeta"
# head(personas)       
# str(personas)  
# summary(personas) 
# colnames(personas) 
# nrow(personas)  
# ncol(personas)
# View(personas) se abre en RStudio como una tabla interactiva.
# write_csv(personas, "data/personas.csv")

tabla vista en R (View)

Leer bases de datos

En la práctica, los datos vienen archivos externos:CSV, Excel, TXT, o bases de datos online. El formato .csv (comma separated values) es el más común. Cada columna está separada por una coma o punto y coma.

library(here)
# CSV
datos_csv <- read.csv(here("data/personas.csv"))
head(datos_csv)
     NAME AGE HEIGHT       JOB
1   Laura  23   1.65   Bióloga
2   Rocio  35   1.80 Profesora
3 Violeta  29   1.70    Médica
# EXCEL
library(readxl)
datos_excel <- read_excel(here("data/herbarium_df.xlsx")) #, sheet = 1 podríamos especificar el numero de hoja
head(datos_excel)
# A tibble: 6 × 19
     ID Collector        Collection_number Assistants  Family Taxon Author det  
  <dbl> <chr>            <chr>             <chr>       <chr>  <chr> <chr>  <chr>
1     1 Hermione Granger 2.0               Sprout, P.… SOLAN… Mand… L.     Spro…
2     2 Ron Weasley      5.0               Potter, H.  SALIC… Sali… Huff.  Spro…
3     3 Dobby H.E.       1.0               Winky H.E.  Zoste… Zost… (Huff… Long…
4     4 Pomona Sprout    1990-301a         Dumbledore… Suffo… Luci… Slyth. Spro…
5     5 Luna Lovegood    5.0               Xenophiliu… rosac… Prun… Rav.   Love…
6     6 Algie Longbottom 3.0               Longbottom… Mimbu… Mimb… Spore  Spro…
# ℹ 11 more variables: Det_date <chr>, life_form <chr>, Observations <chr>,
#   Height <chr>, Location <chr>, Area_description <chr>, Elevation <chr>,
#   Date <chr>, Latitude <chr>, Longitude <chr>, QR_code <chr>
# GOOGLE SHEETS
library(googlesheets4)
datos_gs <- read_sheet("https://docs.google.com/spreadsheets/d/1qC4lsXPpEcX1NmLdwiMJMC8X_WKX-EFQm4ahPdrNCZc/edit?usp=sharing")
head(datos_gs)
# A tibble: 4 × 5
  Nombre             Fecha               Titulo             Tipo.comm Afiliacion
  <chr>              <dttm>              <chr>              <chr>     <chr>     
1 Severus Snape      1993-01-01 00:00:00 Pociones avanzada… oral      Slytherin 
2 Minerva McGonagall 1994-01-01 00:00:00 De gato a humano:… poster    Gryffindor
3 Alastor Moody      1995-01-01 00:00:00 Distinguir entre … oral      Gryffindor
4 Rubeus Hagrid      1996-01-01 00:00:00 ¿Por qué no vuela… oral      Gryffindor
#write_csv(datos_gs, "data/datos_gs.csv")

Ejercicios 3

Base de datos de flores: Por cada sitio y pantrap, tenemos el numero de flores que tienen las especies de plantas en Doñana. Ejercicio: Importa la base de datos “flores.csv” de la carpeta “data”, explora la base de datos, calcula la abundancia media de flores total, indica cuantas especies distintas hay de plantas.

flores <- read.csv(here("data/flores.csv"))
str(flores)
'data.frame':   490 obs. of  5 variables:
 $ code     : int  1 2 3 4 5 6 7 8 9 10 ...
 $ site_id  : chr  "ANZ_1" "ANZ_1" "ANZ_1" "ANZ_1" ...
 $ pantrap  : int  1 1 1 2 2 2 2 3 3 4 ...
 $ species  : chr  "Oxalis pes-caprae" "Cistus salvifolius" "Ornithogalum umbellatum" "Cistus salvifolius" ...
 $ abundance: int  3 16 4 2 3 4 1 3 1 8 ...
mean(flores$abundance)
[1] 16.45102
length(unique(flores$species))
[1] 74
#write_csv (flores, "data/flores.csv")

Compartir código

  • git. Es una herramienta de control de versiones que además permite trabajar en equipo
  • GitHub (portfolio de programador) Perfil

Escribir textos, informes, artículos

  • Quarto
  • Rmarkdown
  • Ciencia reproducible y limpia

Bibliografía

cookbook :::::